package com.cloudm.technician.common.login

import com.cloudm.technician.BaseTestRule
import com.cloudm.technician.data.contants.Constant
import com.cloudm.technician.data.db.DbHelper
import com.cloudm.technician.data.model.Response
import com.cloudm.technician.data.model.User
import com.cloudm.technician.data.network.CommonApi
import com.cloudm.technician.data.preferences.PreferencesHelper
import com.cloudm.technician.ui.modules.common.login.LoginContract
import com.cloudm.technician.ui.modules.common.login.LoginPresenter
import com.google.gson.JsonParseException
import io.reactivex.Observable
import io.reactivex.ObservableOnSubscribe
import org.json.JSONException
import org.junit.Before
import org.junit.Test
import org.mockito.Mock
import org.mockito.Mockito.*
import org.mockito.MockitoAnnotations
import java.net.ConnectException
import java.net.SocketException
import java.net.SocketTimeoutException

/**
 * 作者: wesley
 * 时间: 2017/12/18
 * 描述: 登陆界面presenter层的单元测试
 */
class LoginPresenterTest : BaseTestRule() {
    @Mock private lateinit var view: LoginContract.View
    @Mock private lateinit var commonApi: CommonApi
    @Mock private lateinit var preferencesHelper: PreferencesHelper
    @Mock private lateinit var dbHelper: DbHelper
    private lateinit var presenter: LoginPresenter


    private val phoneNumber = "18255215889"
    private val password = "111111"


    @Before
    fun setUp() {
        MockitoAnnotations.initMocks(this)
        presenter = LoginPresenter(view, commonApi, preferencesHelper, dbHelper)
    }

    @Test
    fun testLoginOne() {
        presenter.login(null, null)
        verify(view).showInputPhoneNumberMsg()
    }

    @Test
    fun testLoginTwo() {
        presenter.login("", null)
        verify(view).showInputPhoneNumberMsg()
    }

    @Test
    fun testLoginThree() {
        presenter.login("    ", null)
        verify(view).showInputPhoneNumberMsg()
    }

    @Test
    fun testLoginFour() {
        presenter.login("    111   ", null)
        verify(view, never()).showInputPhoneNumberMsg()
    }


    @Test
    fun testLoginFive() {
        presenter.login("23456789121", null)
        verify(view).showPhoneNumberFormatMsg()
    }

    @Test
    fun testLoginSix() {
        presenter.login("1345678911", null)
        verify(view).showPhoneNumberFormatMsg()
    }


    @Test
    fun testLoginSeven() {
        presenter.login("13456789121", null)
        verify(view, never()).showPhoneNumberFormatMsg()
    }


    @Test
    fun testLoginEight() {
        presenter.login(phoneNumber, null)
        verify(view).showPasswordEmptyMsg()
    }

    @Test
    fun testLoginNine() {
        presenter.login(phoneNumber, "")
        verify(view).showPasswordEmptyMsg()
    }

    @Test
    fun testLoginTen() {
        val user = User()
        user.token = "1111"
        val response = Response(800, "", user, null)
        val observable = Observable.create(
                ObservableOnSubscribe<Response<User?>> { e -> e.onNext(response) })
        `when`(commonApi.login(phoneNumber, password)).thenReturn(observable)
        `when`(view.isActive).thenReturn(true)
        presenter.login(phoneNumber, password)
        verify(view).showLoginDialog()
        verify(view).hideLoginDialog()
        verify(view).loginSuccess()
        verify(preferencesHelper).isLogin = true
        verify(preferencesHelper).token = user.token
        verify(dbHelper).insertOrUpdateUser(user)
    }

    @Test
    fun testLoginEleven() {
        val response = Response<User>(800, "", null, null)
        val observable = Observable.create(
                ObservableOnSubscribe<Response<User?>> { e -> e.onNext(response) })
        `when`(commonApi.login(phoneNumber, password)).thenReturn(observable)
        `when`(view.isActive).thenReturn(true)
        presenter.login(phoneNumber, password)
        verify(view).showLoginDialog()
        verify(view).hideLoginDialog()
        verify(view).showUserEmptyMsg()
    }

    @Test
    fun testLoginTwelve() {
        val response = Response<User>(300, "", null, null)
        val observable = Observable.create(
                ObservableOnSubscribe<Response<User?>> { e -> e.onNext(response) })
        `when`(commonApi.login(phoneNumber, password)).thenReturn(observable)
        `when`(view.isActive).thenReturn(true)
        presenter.login(phoneNumber, password)
        verify(view).showLoginDialog()
        //verify(view).openActivity()
    }

    @Test
    fun testLoginThirteen() {
        val message = "error"
        val response = Response<User>(301, message, null, null)
        val observable = Observable.create(
                ObservableOnSubscribe<Response<User?>> { e -> e.onNext(response) })
        `when`(commonApi.login(phoneNumber, password)).thenReturn(observable)
        `when`(view.isActive).thenReturn(true)
        presenter.login(phoneNumber, password)
        verify(view).showLoginDialog()
        verify(view).loginFailure(message)
    }


    @Test
    fun testLoginFourteen() {
        val exception = ConnectException()
        val observable = Observable.create(
                ObservableOnSubscribe<Response<User?>> { e -> e.onError(exception) })
        `when`(commonApi.login(phoneNumber, password)).thenReturn(observable)
        `when`(view.isActive).thenReturn(true)
        presenter.login(phoneNumber, password)
        verify(view).showLoginDialog()
        verify(view).loginFailure(Constant.CANNOT_CONTACT_TO_SERVER)
    }

    @Test
    fun testLoginFifteen() {
        val exception = SocketException()
        val observable = Observable.create(
                ObservableOnSubscribe<Response<User?>> { e -> e.onError(exception) })
        `when`(commonApi.login(phoneNumber, password)).thenReturn(observable)
        `when`(view.isActive).thenReturn(true)
        presenter.login(phoneNumber, password)
        verify(view).showLoginDialog()
        verify(view).loginFailure(Constant.NETWORK_ERROR)
    }


    @Test
    fun testLoginSixteen() {
        val exception = SocketTimeoutException()
        val observable = Observable.create(
                ObservableOnSubscribe<Response<User?>> { e -> e.onError(exception) })
        `when`(commonApi.login(phoneNumber, password)).thenReturn(observable)
        `when`(view.isActive).thenReturn(true)
        presenter.login(phoneNumber, password)
        verify(view).showLoginDialog()
        verify(view).loginFailure(Constant.CONNECT_TIME_OUT)
    }


    @Test
    fun testLoginSevenTeen() {
        val exception = JsonParseException("")
        val observable = Observable.create(
                ObservableOnSubscribe<Response<User?>> { e -> e.onError(exception) })
        `when`(commonApi.login(phoneNumber, password)).thenReturn(observable)
        `when`(view.isActive).thenReturn(true)
        presenter.login(phoneNumber, password)
        verify(view).showLoginDialog()
        verify(view).loginFailure(Constant.DATA_PARSE_EXCEPTION)
    }


    @Test
    fun testLoginEighteen() {
        val exception = JSONException("")
        val observable = Observable.create(
                ObservableOnSubscribe<Response<User?>> { e -> e.onError(exception) })
        `when`(commonApi.login(phoneNumber, password)).thenReturn(observable)
        `when`(view.isActive).thenReturn(true)
        presenter.login(phoneNumber, password)
        verify(view).showLoginDialog()
        verify(view).loginFailure(Constant.DATA_PARSE_EXCEPTION)
    }

    @Test
    fun testLoginNineteen() {
        val exception = Throwable()
        val observable = Observable.create(
                ObservableOnSubscribe<Response<User?>> { e -> e.onError(exception) })
        `when`(commonApi.login(phoneNumber, password)).thenReturn(observable)
        `when`(view.isActive).thenReturn(true)
        presenter.login(phoneNumber, password)
        verify(view).showLoginDialog()
        verify(view).loginFailure(Constant.UNKNOWN_ERROR)
    }

    @Test
    fun testUpdateBtnStatusOne(){
        `when`(view.getPhoneNumber()).thenReturn("")
        presenter.updateBtnStatus()
        verify(view).btnLoginNotEnabled()
    }

    @Test
    fun testUpdateBtnStatusTwo(){
        `when`(view.getPhoneNumber()).thenReturn("   ")
        presenter.updateBtnStatus()
        verify(view).btnLoginNotEnabled()
    }


    @Test
    fun testUpdateBtnStatusThree(){
        `when`(view.getPhoneNumber()).thenReturn(phoneNumber)
        `when`(view.getPassword()).thenReturn("")
        presenter.updateBtnStatus()
        verify(view).btnLoginNotEnabled()
    }

    @Test
    fun testUpdateBtnStatusFour(){
        `when`(view.getPhoneNumber()).thenReturn(phoneNumber)
        `when`(view.getPassword()).thenReturn("   ")
        presenter.updateBtnStatus()
        verify(view).btnLoginEnabled()
    }

    @Test
    fun testUpdateBtnStatusFive(){
        `when`(view.getPhoneNumber()).thenReturn(phoneNumber)
        `when`(view.getPassword()).thenReturn(null)
        presenter.updateBtnStatus()
        verify(view).btnLoginNotEnabled()
    }


    @Test
    fun testUpdateIvClearPhoneStatusOne(){
        presenter.updateIvClearPhoneStatus(0, null)
        verify(view).setIvClearPhoneNotVisible()
    }


    @Test
    fun testUpdateIvClearPhoneStatusTwo(){
        presenter.updateIvClearPhoneStatus(0, "")
        verify(view).setIvClearPhoneNotVisible()
    }


    @Test
    fun testUpdateIvClearPhoneStatusThree(){
        presenter.updateIvClearPhoneStatus(0, "   ")
        verify(view).setIvClearPhoneNotVisible()
    }


    @Test
    fun testUpdateIvClearPhoneStatusFour(){
        presenter.updateIvClearPhoneStatus(0, "  111 ")
        verify(view).setIvClearPhoneVisible()
    }


    @Test
    fun testUpdateIvClearPhoneStatusOnes(){
        presenter.updateIvClearPhoneStatus(false)
        verify(view).setIvClearPhoneNotVisible()
    }


    @Test
    fun testUpdateIvClearPhoneStatusTwos(){
        `when`(view.getPhoneNumber()).thenReturn("  11  ")
        presenter.updateIvClearPhoneStatus(true)
        verify(view).setIvClearPhoneVisible()
    }

}